package com.alex.statistics.method.structureanalysis;

import com.alex.statistics.pojo.request.structureanalysis.DynamicStructureRequest;
import com.alex.statistics.pojo.result.structureanalysis.DynamicStructureResult;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class DynamicStructureService {

    /**
     * 结构变化指数分析：计算各组成部分在两个时期的结构变动幅度
     */
    public DynamicStructureResult.StructureChangeIndexResult calculateStructureChangeIndex(DynamicStructureRequest.StructureChangeIndexRequest request) {
        long startTime = System.currentTimeMillis();
        validateStructureChangeRequest(request);

        // 计算基期和报告期的总值
        double baseTotal = request.getBasePeriodValues().stream().mapToDouble(Double::doubleValue).sum();
        double reportTotal = request.getReportPeriodValues().stream().mapToDouble(Double::doubleValue).sum();

        // 计算各组成部分的结构变化
        List<DynamicStructureResult.StructureChangeIndexResult.StructureChangeDetail> details = new ArrayList<>();
        double totalChangeIndex = 0.0;

        for (int i = 0; i < request.getComponentNames().size(); i++) {
            String name = request.getComponentNames().get(i);
            double baseValue = request.getBasePeriodValues().get(i);
            double reportValue = request.getReportPeriodValues().get(i);

            // 计算基期和报告期的占比
            double baseProportion = (baseValue / baseTotal) * 100;
            double reportProportion = (reportValue / reportTotal) * 100;

            // 计算结构变化指数（变动幅度的绝对值）
            double changeIndex = Math.abs(reportProportion - baseProportion);
            totalChangeIndex += changeIndex;

            details.add(new DynamicStructureResult.StructureChangeIndexResult.StructureChangeDetail(
                    name, baseProportion, reportProportion, changeIndex
            ));
        }

        // 计算整体结构变化指数（平均值）
        double overallIndex = totalChangeIndex / request.getComponentNames().size();

        // 构建结果
        DynamicStructureResult.StructureChangeIndexResult result = new DynamicStructureResult.StructureChangeIndexResult();
        result.setComputeTime(System.currentTimeMillis() - startTime);
        result.setBasePeriodTotal(baseTotal);
        result.setReportPeriodTotal(reportTotal);
        result.setDetails(details);
        result.setOverallChangeIndex(overallIndex);
        return result;
    }

    /**
     * 贡献度分析：计算各因素对整体指标变化的贡献值和贡献比例
     */
    public DynamicStructureResult.ContributionResult calculateContribution(DynamicStructureRequest.ContributionRequest request) {
        long startTime = System.currentTimeMillis();
        validateContributionRequest(request);

        // 计算整体变动值
        double totalChange = request.getReportPeriodTotal() - request.getBasePeriodTotal();

        // 计算各因素的贡献度
        List<DynamicStructureResult.ContributionResult.ContributionDetail> details = new ArrayList<>();
        for (int i = 0; i < request.getFactorNames().size(); i++) {
            String name = request.getFactorNames().get(i);
            double baseValue = request.getBasePeriodFactors().get(i);
            double reportValue = request.getReportPeriodFactors().get(i);
            double factorChange = reportValue - baseValue;

            // 计算贡献值（因素变动值占总变动的比例乘以整体变动值）
            double contributionValue = (factorChange / sumFactorChanges(request)) * totalChange;
            double contributionRatio = (contributionValue / totalChange) * 100;

            details.add(new DynamicStructureResult.ContributionResult.ContributionDetail(
                    name, baseValue, reportValue, factorChange, contributionValue, contributionRatio
            ));
        }

        // 构建结果
        DynamicStructureResult.ContributionResult result = new DynamicStructureResult.ContributionResult();
        result.setComputeTime(System.currentTimeMillis() - startTime);
        result.setBasePeriodTotal(request.getBasePeriodTotal());
        result.setReportPeriodTotal(request.getReportPeriodTotal());
        result.setTotalChange(totalChange);
        result.setDetails(details);
        return result;
    }

    // 辅助方法：计算所有因素的总变动值
    private double sumFactorChanges(DynamicStructureRequest.ContributionRequest request) {
        double sum = 0.0;
        for (int i = 0; i < request.getFactorNames().size(); i++) {
            sum += (request.getReportPeriodFactors().get(i) - request.getBasePeriodFactors().get(i));
        }
        return sum;
    }

    // 参数校验：结构变化指数
    private void validateStructureChangeRequest(DynamicStructureRequest.StructureChangeIndexRequest request) {
        if (request.getComponentNames() == null || request.getComponentNames().isEmpty()) {
            throw new IllegalArgumentException("组成部分名称不能为空");
        }
        if (request.getBasePeriodValues() == null || request.getBasePeriodValues().isEmpty()) {
            throw new IllegalArgumentException("基期数值不能为空");
        }
        if (request.getReportPeriodValues() == null || request.getReportPeriodValues().isEmpty()) {
            throw new IllegalArgumentException("报告期数值不能为空");
        }
        if (request.getComponentNames().size() != request.getBasePeriodValues().size() ||
                request.getComponentNames().size() != request.getReportPeriodValues().size()) {
            throw new IllegalArgumentException("组成部分名称与数值的数量必须一致");
        }
        if (request.getBasePeriodValues().stream().anyMatch(v -> v < 0) ||
                request.getReportPeriodValues().stream().anyMatch(v -> v < 0)) {
            throw new IllegalArgumentException("基期和报告期数值不能为负数");
        }
    }

    // 参数校验：贡献度分析
    private void validateContributionRequest(DynamicStructureRequest.ContributionRequest request) {
        if (request.getFactorNames() == null || request.getFactorNames().isEmpty()) {
            throw new IllegalArgumentException("因素名称不能为空");
        }
        if (request.getBasePeriodFactors() == null || request.getBasePeriodFactors().isEmpty()) {
            throw new IllegalArgumentException("基期因素值不能为空");
        }
        if (request.getReportPeriodFactors() == null || request.getReportPeriodFactors().isEmpty()) {
            throw new IllegalArgumentException("报告期因素值不能为空");
        }
        if (request.getFactorNames().size() != request.getBasePeriodFactors().size() ||
                request.getFactorNames().size() != request.getReportPeriodFactors().size()) {
            throw new IllegalArgumentException("因素名称与因素值的数量必须一致");
        }
        if (request.getBasePeriodTotal() == null || request.getBasePeriodTotal() <= 0) {
            throw new IllegalArgumentException("基期整体总值必须大于0");
        }
        if (request.getReportPeriodTotal() == null || request.getReportPeriodTotal() <= 0) {
            throw new IllegalArgumentException("报告期整体总值必须大于0");
        }
    }
}
    